package egin

import (
	"context"
	"egin/pkg/config"
	"egin/pkg/gi18n"
	"egin/pkg/ws"
	"egin/router"

	"html/template"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/gin-contrib/pprof"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"

	"net/http"
)

func Run() *http.Server {

	egin := gin.New()
	pprof.Register(egin) // 性能
	//加载模版文件
	if config.C().View.IsLoad {

		egin.SetFuncMap(template.FuncMap{
			"lang": gi18n.Lang,
		})

		egin.LoadHTMLGlob(config.C().View.Path)

	}

	//判断是否 加载静态资源
	if config.C().View.IsLoadStatic {

		egin.StaticFS("/public", http.Dir(config.C().View.StaticPath))
	}

	//路由&中间件
	router.SetRouter(egin)

	//websocket
	if config.C().Websocket.Start == 1 {
		// websocket 管理中心hub全局初始化一份
		ws.WebsocketClientManager = ws.NewClientManager()
		if Wh, ok := ws.WebsocketClientManager.(*ws.ClientManager); ok {
			go Wh.Run()
		}
	}

	srv := &http.Server{
		Addr:         config.C().App.Host + ":" + config.C().App.Port,
		Handler:      egin,
		ReadTimeout:  30 * time.Second,
		WriteTimeout: 30 * time.Second,
	}

	// Initializing the server in a goroutine so that
	// it won't block the graceful shutdown handling below
	go func() {
		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			zap.L().Fatal("listen: ", zap.Error(err))
		}
	}()

	// Wait for interrupt signal to gracefully shutdown the server with
	// a timeout of 5 seconds.
	quit := make(chan os.Signal, 1)
	// kill (no param) default send syscall.SIGTERM
	// kill -2 is syscall.SIGINT
	// kill -9 is syscall.SIGKILL but can't be catch, so don't need add it
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit
	zap.L().Info("Shutting down server...")

	// The context is used to inform the server it has 5 seconds to finish
	// the request it is currently handling
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	if err := srv.Shutdown(ctx); err != nil {
		zap.L().Fatal("Server forced to shutdown:", zap.Error(err))
	}

	zap.L().Info("Server exiting")
	return srv
}
